package org.reborn.engine.render.texture

import org.reborn.utils.niobuffer.BufferUtil
import org.reborn.utils.FileUtil

import java.nio.{Buffer,ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,FloatBuffer,LongBuffer,DoubleBuffer}

import javax.media.opengl.{GL,GL2,GL2GL3,GL2ES2}
import javax.imageio.ImageIO
import java.awt.image.{BufferedImage,Raster}
import java.awt.Image

import TextureType._

trait TextureManager1DSupport {
  self:CachingTextureManager =>
	
  private val TEST_TEX_1D = "Test Texture 1D";
  
  private implicit def defaultTexture1D(gl:GL):Texture1D = TestTexture1D(gl)
  
  /**
   * Create a Texture1D texture, using the default texture metadata.
   * @param gl the GL object so that JOGL operations can be performed
   * @param textureData a Seq of java.nio.Buffer objects that contain the image data.
   * @param width width of the texture data in pixels
   * @param glFormat the format of the texture data (GL_RGB, GL_RGBA, GL_LUMINENCE, etc...)
   * @param glType the type of data in the textureData buffer (GL_UNSIGNED_BYTE, GL_INT, GL_FLOAT, etc...)
   * This type must correspond to the type of Buffer implementation used by textureData
   * @return the Texture1D object
   */
  def Texture1D(gl:GL,textureData:Seq[Buffer],width:Int,glFormat:Int,glType:Int):Texture1D = {
	val metadata = default1DMetadata
    metadata.width = width
    
    return Texture1D(gl,textureData,metadata,glFormat,glType)
  }
  
  /**
   * Create a Texture1D texture. 
   * @param gl the GL object so that JOGL operations can be performed
   * @param textureData an Seq of java.nio.Buffer objects that contain the image data.
   * @param textureMetadata the metadata of the texture (width, internal format, etc...)
   * @param glFormat the format of the texture data (GL_RGB, GL_RGBA, GL_LUMINENCE, etc...)
   * @param glType the type of data in the textureData buffer (GL_UNSIGNED_BYTE, GL_INT, GL_FLOAT, etc...)
   * This type must correspond to the type of Buffer implementation used by textureData
   * @return the Texture1D object
   */
  def Texture1D(gl:GL,textureData:Seq[Buffer],textureMetadata:Texture1DMetadata,glFormat:Int,glType:Int):Texture1D = {
	val textureKey = (getNewBufferFileName,Tex1D)
    val tex:Texture1D = addTextureToMap(gl,textureKey){()=>
      Some(createTexture1DFromBuffer(gl,textureData,textureMetadata,glFormat,glType))
    }
    
    tex
  }
  
  /**
   * Load an image and create a Texture1D object
   * @param gl the GL object so that JOGL operations can be performed
   * @param fileName The name of the image file to load
   * @param textureMetadata the metadata of the texture (internal format, etc...). The 
   * width attribute of the metadata will be overwritten by the actual width of the 
   * image file.
   */
  def Texture1D(gl:GL,fileName:String,textureMetadata:Texture1DMetadata):Texture1D = {
	val textureKey = (fileName,Tex1D)
	
	val tex:Texture1D = addTextureToMap(gl,textureKey){()=>
	  val dataOpt = getImgDataFromFile(fileName)
	  if(dataOpt.isEmpty){
	    System.err.println("Could not find image, or image was not in a supported format: "+fileName)
	    None
	  }
	  else{
	    val (width,height,glFormat,glType,buffer) = dataOpt.get
	    textureMetadata.width = width
	    textureMetadata.glInternalFormat = glFormat
	    Some(createTexture1DFromBuffer(gl,Array(buffer),textureMetadata,glFormat,glType))
	  }
	}
	
	tex
  }
  
  /**
   * Load an image and create a Texture1D object using the default metadata
   * @param gl the GL object so that JOGL operations can be performed
   * @param fileName The name of the image file to load
   */
  def Texture1D(gl:GL,fileName:String):Texture1D = {
	val metadata = default1DMetadata
	Texture1D(gl,fileName,metadata)
  }
  
  /**
   * Creates a test texture 1D object. This texture is also returned if 
   * there is an error loading a 1D texture from a file
   * @param gl the GL object so that JOGL operations can be performed
   */
  def TestTexture1D(gl:GL):Texture1D = {
	val textureKey = (TEST_TEX_1D,Tex1D)
	
	val tex:Texture1D = addTextureToMap(gl,textureKey){()=>
	  val metadata = new Texture1DMetadata
	  metadata.width=4
	  metadata.magFilter = TextureFilter.Nearest
	  metadata.minFilter = TextureFilter.Nearest
	  metadata.glInternalFormat = GL.GL_RGBA 
	
	  val image = testTextureBuffer
		
	  Some(createTexture1DFromBuffer(gl,Array(image),metadata,GL.GL_RGBA,GL.GL_UNSIGNED_BYTE))
	}
	tex
  }
  
  /**
   * Creates a Texture1DMetadata object with the current TextureManager 
   * metadata values. This metadata object will also be used for any
   * texture creation operation where metadata is not explicitly passed
   * as a parameter.
   */
  def default1DMetadata:Texture1DMetadata = {
	val metadata = new Texture1DMetadata
	updateCommonMetadata(metadata)
	return metadata
  }
  
  protected def createTexture1DFromBuffer(gl:GL,textureData:Seq[Buffer],textureMetadata:Texture1DMetadata,glFormat:Int,glType:Int):Texture1D = {
    val text = new Texture1D(textureMetadata)
    text.createTexture(gl,textureData,glFormat,glType)
    return text
  }
}